package com.version1.diabeco.data.peso;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.version1.diabeco.data.AbstractDao;
import com.version1.diabeco.data.DiabecoContract;
import com.version1.diabeco.model.peso.Peso;

public class PesoDaoImpl extends AbstractDao implements PesoDao {

	private Context context;
	private static PesoDaoImpl instance;


	private static final String[] PESO_FIELDS = {
			DiabecoContract.RegistroPeso._ID,
			DiabecoContract.RegistroPeso.COLUMNA_ALIAS,
			DiabecoContract.RegistroPeso.COLUMNA_FECHA,
			DiabecoContract.RegistroPeso.COLUMNA_PESO,
			DiabecoContract.RegistroPeso.COLUMNA_UM_PESO,
			DiabecoContract.RegistroPeso.COLUMNA_IMC,
			DiabecoContract.RegistroPeso.COLUMNA_IMC_TIPO};

		
	protected PesoDaoImpl(Context context) {
		super(context);
	}

	
/**
* Retrieves the singleton instance. Receives a context which is used for database initialization but also stored
* for subsequent sql operation calls.
* 
* This method is thread-safe.
* 
* @return PesoDao with the instance.
*/
	public static synchronized PesoDaoImpl getInstance(Context context) {
		if (instance == null) {
			instance = new PesoDaoImpl(context);
		}

		instance.setContext(context);
		return instance;
	}

	public Context getContext() {
		return context;
	}

	public void setContext(Context context) {
		this.context = context;
	}


	@Override
	public Long count() {
		// TODO Auto-generated method stub
		return null;
	}

	
	@Override
	public List<Peso> selectAll() {

		List<Peso> result = new ArrayList<Peso>();
		
		SQLiteDatabase db = PesoDaoImpl.getInstance(this.getContext()).getReadableDatabase();

		String selection = null;
		String[] selectionArgs = null;

		// How you want the results sorted in the resulting Cursor
		String sortOrder = DiabecoContract.RegistroPeso.COLUMNA_FECHA + " DESC";
		
		Cursor cursorPeso = db.query(DiabecoContract.RegistroPeso.TABLE_NAME, // The table to query
				PESO_FIELDS, // The columns to return
				selection, // The columns for the WHERE clause
				selectionArgs, // The values for the WHERE clause
				null, // don't group the rows
				null, // don't filter by row groups
				sortOrder // The sort order
		);

		while (cursorPeso.moveToNext()) {
			Peso peso = this.retrievePesoFromCursor(cursorPeso);
			result.add(peso);
		}

		db.close();
		return result;
	}

	
	@Override
	public Peso selectById(Long id) {

		Peso result = null;

		//Base de datos en Modo Lectura
		SQLiteDatabase db = PesoDaoImpl.getInstance(this.getContext()).getReadableDatabase();
		
		//Armamos el Where
		String selection = DiabecoContract.RegistroPeso._ID + " = ?";
		String[] selectionArgs = { id.toString() };

		//Orden en que se devuelven los datos consultados
		String sortOrder = DiabecoContract.RegistroPeso.COLUMNA_FECHA + " DESC";

		Cursor cursor = db.query(DiabecoContract.RegistroPeso.TABLE_NAME, // The table to query
				PESO_FIELDS, // The columns to return
				selection, // The columns for the WHERE clause
				selectionArgs, // The values for the WHERE clause
				null, // don't group the rows
				null, // don't filter by row groups
				sortOrder // The sort order
				);

		result = this.retrievePesoFromCursor(cursor);

		db.close();
		return result;
	}

	
	@Override
	public List<Peso> select5Dias() {

		// FIXME deberia filtrar directo en la base.
		List<Peso> lista5dias = new ArrayList<Peso>();
		List<Peso> listaCompleta = this.selectAll();
		 
		Calendar c = Calendar.getInstance();
		Date now = new Date();
		c.setTime(now);
		c.add(Calendar.DATE, -5);
		c.clear(Calendar.HOUR_OF_DAY);
		c.clear(Calendar.MINUTE);
		Long hace5diasDate = c.getTime().getTime();

		for (Peso peso : listaCompleta) {
			if (peso.getFecha() > hace5diasDate) {
				lista5dias.add(peso);
			}
		}
		
		return lista5dias;
	}


	@Override
	public void save(Peso peso) {

		// Gets the data repository in write mode
		SQLiteDatabase db = PesoDaoImpl.getInstance(this.getContext()).getWritableDatabase();

		// Create a new map of values, where column names are the keys
		ContentValues values = new ContentValues();
		values.put(DiabecoContract.RegistroPeso.COLUMNA_ALIAS, peso.getAlias());
		values.put(DiabecoContract.RegistroPeso.COLUMNA_FECHA, peso.getFecha());
		values.put(DiabecoContract.RegistroPeso.COLUMNA_PESO, peso.getPeso());
		values.put(DiabecoContract.RegistroPeso.COLUMNA_UM_PESO, peso.getUm());
		values.put(DiabecoContract.RegistroPeso.COLUMNA_IMC, peso.getImc());
		values.put(DiabecoContract.RegistroPeso.COLUMNA_IMC_TIPO, peso.getImcTipo());
		
		// Insert the new row, returning the primary key value of the new row
		long rowId;
		if (peso.getId() != null) {
			rowId = db.update(DiabecoContract.RegistroPeso.TABLE_NAME, values,
					DiabecoContract.RegistroPeso._ID + " = ?", new String[] { peso.getId().toString() });
		} else {
			// Insert the new row, returning the primary key value of the new row
			rowId = db.insert(DiabecoContract.RegistroPeso.TABLE_NAME, null, values);
		}

		System.out.println("Registros grabados en la base de datos: " + rowId);
		db.close();
	}

	
	@Override
	public void deleteById(Long id) {

		// Gets the data repository in write mode
		SQLiteDatabase db = PesoDaoImpl.getInstance(this.getContext()).getWritableDatabase();

		String removeId = id.toString();

		int rowsDeleted = db.delete(DiabecoContract.RegistroPeso.TABLE_NAME, DiabecoContract.RegistroPeso._ID + "=?",
				new String[] { removeId });

		if (rowsDeleted != 1) {
			throw new RuntimeException("No se pudo eliminar el registro con id " + id);
		}

		// Cerramos Base de Datos
		db.close();
	}

	
	@Override
	public void clear() {
		// TODO Auto-generated method stub
	}
	

	private Peso retrievePesoFromCursor(Cursor cursor) {
		
		//Obtengo los datos del cursor
		Long id 	    = cursor.getLong(cursor.getColumnIndexOrThrow(DiabecoContract.RegistroPeso._ID));
		String alias    = cursor.getString(cursor.getColumnIndexOrThrow(DiabecoContract.RegistroPeso.COLUMNA_ALIAS));
		Long date 	    = cursor.getLong(cursor.getColumnIndexOrThrow(DiabecoContract.RegistroPeso.COLUMNA_FECHA));
		float pesoCant  = cursor.getFloat(cursor.getColumnIndexOrThrow(DiabecoContract.RegistroPeso.COLUMNA_PESO));
		String um_peso  = cursor.getString(cursor.getColumnIndexOrThrow(DiabecoContract.RegistroPeso.COLUMNA_UM_PESO));
		float imc       = cursor.getFloat(cursor.getColumnIndexOrThrow(DiabecoContract.RegistroPeso.COLUMNA_IMC));
		String imc_tipo = cursor.getString(cursor.getColumnIndexOrThrow(DiabecoContract.RegistroPeso.COLUMNA_IMC_TIPO));
		
		//Cargamos el objeto de negocio PESO
		Peso peso = new Peso();
		peso.setId(id);
		peso.setAlias(alias);
		peso.setFecha(date);
		peso.setPeso(pesoCant);
		peso.setUm(um_peso);
		peso.setImc(imc);
		peso.setImcTipo(imc_tipo);
		
		System.out.println("Readed weight: " + peso);
		return peso;
	}	

	
	
	
	public List<Peso> selectBetweenDatesAndValues(Calendar fromDate, Calendar toDate/*, Float umbralBajo, Float umbralAlto, long rango, long observaciones*/) {
		List<Peso> result = new ArrayList<Peso>();
	
		//Agregar SYSTEM.OUT para asegurar que llega parametro
		
		PesoDaoImpl.getInstance(this.getContext()).getReadableDatabase();
		
		SQLiteDatabase db = PesoDaoImpl.getInstance(this.getContext()).getReadableDatabase();

		
		Cursor cursor;
		String sortOrder = DiabecoContract.RegistroGlucosa.COLUMNA_FECHA + " DESC";
		String selection = DiabecoContract.RegistroGlucosa.COLUMNA_FECHA + " >= ? AND " + DiabecoContract.RegistroGlucosa.COLUMNA_FECHA + " <= ? ";
		String[] selectionArgs = {String.valueOf(fromDate.getTimeInMillis()), String.valueOf(toDate.getTimeInMillis())};

				// How you want the results sorted in the resulting Cursor
				cursor = db.query(DiabecoContract.RegistroPeso.TABLE_NAME, // The table to query
						PESO_FIELDS, // The columns to return
						selection, // The columns for the WHERE clause
						selectionArgs, // The values for the WHERE clause
						null, // don't group the rows
						null, // don't filter by row groups
						sortOrder // The sort order
						);
	

		while (cursor.moveToNext()) {
			Peso peso = this.retrievePesoFromCursor(cursor);
			result.add(peso);
		}

		return result;
	}
	
}